﻿// ===============================================================================
// TableSchema.cs
// EOS Framework
// ===============================================================================
// Copyright (c) EOS Development Group. All rights reserved.
// ===============================================================================

namespace EOS.Framework.Contracts.Schema
{
    using System;
    using EOS.Framework.Tools;

    /// <summary>
    /// Provides Schema Information about a table.
    /// </summary>
    [Serializable]
    public class TableSchema : IEquatable<TableSchema>
    {
        #region Properties

        /// <summary>
        /// The name of the table.
        /// </summary>
        private string _name;

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name of the table. Cannot be null or empty or contains only blanks.</value>
        /// <exception cref="ArgumentNullException"><paramref name="value"/> is null
        /// (Nothing in Visual Basic).</exception>
        /// <exception cref="ArgumentException"><paramref name="value"/> is a string
        /// of length 0 or has only blanks.</exception>
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        /// <summary>
        /// The name of the Catalog.
        /// </summary>
        private string _catalog;

        /// <summary>
        /// Gets or sets the catalog.
        /// </summary>
        /// <value>The name of the Catalog.</value>
        public string Catalog
        {
            get { return _catalog; }
            set { _catalog = value; }
        }

        /// <summary>
        /// The name of the schema.
        /// </summary>
        private string _schema;

        /// <summary>
        /// Gets or sets the schema.
        /// </summary>
        /// <value>The name of the schema.</value>
        public string Schema
        {
            get { return _schema; }
            set { _schema = value; }
        }

        /// <summary>
        /// A list of table columns.
        /// </summary>
        private ColumnSchemaCollection _columns;

        /// <summary>
        /// Gets the columns.
        /// </summary>
        /// <value>list of table columns.</value>
        public ColumnSchemaCollection Columns
        {
            get 
            {
                if (_columns == null)
                {
                    _columns = new ColumnSchemaCollection();
                }

                return _columns; 
            }
        }

        /// <summary>
        /// A list of references to this table.
        /// </summary>
        private ReferenceSchemaCollection _inReferences;

        /// <summary>
        /// Gets the list of references to this table.
        /// </summary>
        /// <value>A list of references to this table</value>
        public ReferenceSchemaCollection InReferences
        {
            get
            {
                if (_inReferences == null)
                {
                    _inReferences = new ReferenceSchemaCollection();
                }

                return _inReferences;
            }
        }

        /// <summary>
        /// Accessibly list of out references.
        /// </summary>
        private ReferenceSchemaCollection _outReferences;

        /// <summary>
        /// Gets the out references.
        /// </summary>
        /// <value>The out references.</value>
        public ReferenceSchemaCollection OutReferences
        {
            get
            {
                if (_outReferences == null)
                {
                    _outReferences = new ReferenceSchemaCollection();
                }

                return _outReferences;
            }
        }

        /// <summary>
        /// Reference to the database, the table belongs to.
        /// </summary>
        private DatabaseSchema _database;

        /// <summary>
        /// Gets or sets the database, the table belongs to
        /// </summary>
        /// <value>The database. Cannot be null (Nothing in Visual Basic).</value>
        /// <exception cref="ArgumentNullException"><paramref name="value"/> is 
        /// null (Nothing in Visual Basic).</exception>
        public DatabaseSchema Database
        {
            get { return _database; }
            set { _database = value; }
        }

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="TableSchema"/> class.
        /// </summary>
        public TableSchema()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TableSchema"/> class
        /// with the name of the table.
        /// </summary>
        /// <param name="name">The name.</param>
        public TableSchema(string name)
        {
            this._name = name;
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }

            return Equals(obj as TableSchema);
        }

        public bool Equals(TableSchema other)
        {
            if (other == null)
            {
                return false;
            }

            bool result = true;

            if (!Object.Equals(_catalog, other._catalog))
            {
                result = false;
            }

            if (!Object.Equals(_columns, other._columns))
            {
                result = false;
            }

            if (!Object.Equals(_inReferences, other._inReferences))
            {
                result = false;
            }

            if (!Object.Equals(_name, other._name))
            {
                result = false;
            }

            if (!Object.Equals(_outReferences, other._outReferences))
            {
                result = false;
            }

            if (!Object.Equals(_schema, other._schema))
            {
                result = false;
            }

            return result;
        }

        /// <summary>
        /// Serves as a hash function for a particular type.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        public override int GetHashCode()
        {
            int hashCode = 1;

            if (_name != null)
            {
                hashCode ^= _name.GetHashCode();
            }
            if (_catalog != null)
            {
                hashCode ^= _catalog.GetHashCode();
            }
            if (_schema != null)
            {
                hashCode ^= _schema.GetHashCode();
            }
            if (_columns != null)
            {
                hashCode ^= _columns.CreateHashCode();
            }
            if (_inReferences != null)
            {
                hashCode ^= _inReferences.CreateHashCode();
            }
            if (_inReferences != null)
            {
                hashCode ^= _inReferences.CreateHashCode();
            }

            return hashCode;
        }
    }
}
